Herança


    Em POO, falando em termos computacionais, o conceito de heranças tem dois aspectos fundamentais:


        1. Reaproveitar o código de uma classe (classe-pai/super-classe) em diversas outras classes (classes-filhas).

        2. Adicionar o tipo da classe-pai aos tipos das classes-filhas.


    Todos os atributos e métodos da classe-pai (super-classe) estarão presentes nas classes filhas automaticamente. No entanto, valem os encapsulamentos, o que for private não terá visibilidade mesmo na classe filha.


    A palavra extends nas classes-filhas indica herança.


    Fazemos herança seguindo a forma: <encapsulamento> class <nome_da_classe> extends <nome_da_superclasse>{ }


    Mas cuidado: No JAVA só é permitido herdar UMA super-classe


    A dica é: Filhos só tem 1 pai. Pai tem n filhos.


    Usar a super-classe para representar qualquer tipo filho é um conceito-chave de POO chamado POLIMORFISMO.


Herança Múltipla


    Dissemos que no JAVA em qualquer classe só é permitido fazer herança de 1 classe.


    No entanto, existem situações em que gostaríamos de fazer herança de mais de uma super-classe, nesses casos temos que encadear as heranças.


    Ou seja, podemos fazer a super-classe herdar outra super-classe em vez da classe filha fazer herança múltipla.


    Em outras palavras, podemos fazer apenas 1 herança direta em cada classe, mas podemos herdar indiretamente qualquer número de classes.


    O motivo para esse tipo de arquitetura é que no JAVA, assim como em outras liguagens, todas as classes tem uma super-classe em comum.


    No JAVA todas as classes herdam a classe Object, portanto, qualquer classe tem o tipo Object.


    Essa herança é implícita, mesmo sem o comando extends todas as classes herdam Object.


    Mas porque a herança de Object faz com que mais de uma herança direta seja ilegal, mas heranças indiretas sejam permitidas? Se isso acontecer, a Classe acabará herdando Object duas vezes.


    Isso quer dizer que se o compilador não restringisse, acabaríamos com duas cópias de todos os atributos e métodos de Object na Classe. E classes não podem ter atributos com mesmo nome ou métodos com a mesma assinatura, portanto, teríamos um monte de erros.


Sobrescrita de Métodos


    Usamos a técnica de sobrescrita de métodos para fazer em uma classe-filha uma implementação diferente para um método da super-classe.


    Colocamos a diretiva @Override, indicando para o JAVA que não estamos criando um método novo, estamos sobrescrevendo o que já existe.


    Em suma, para sobrescrever a implementação de um método da super-classe em uma classe-filha crie um método na classe-filha com a mesma assinatura do método da classe-pai e na linha anterior utilize o comando @Override.


    É possível utilizar a implementação original usando a diretiva super.


    Para entender como isso é possível precisamos entender como o JAVA gerencia a herança.


    Para todo objeto criado a partir de classes derivadas (filhas) o JAVA cria um objeto da classe-pai.


    O JAVA instancia a superclasse automaticamente e vincula as duas.


    Existe na memória um objeto da classe-pai vinculado ao ciclo de vida de cada objeto da classe-filha.


    Esse é o motivo pelo qual temos acesso aos atributos e métodos da superclasse, mesmo aqueles que sobrescrevemos na classe-filha.


    Por conta disso, construtores da superclasse e das classes-filhas devem ter o mesmo conjunto de parâmetros, ou o código não compilará!


    Para fazer isso usamos super,como método: super(). Isso é equivalente o this() que invocava o construtor da própria classe, mas para a classe-pai.


    Em resumo, para invocar um construtor da superclasse use super().


    Você também pode usar o super() para escolher qual construtor da superclasse rodar se houver mais de um.


    Lembre-se, super() só pode ser invocado na primeira linha do construtor da classe-filha.